
package vcs.bluetoothmusic;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.util.UUID;

import vcs.media.R;
import vcs.media.player.Utilities;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;

/**
 * This is the main Activity that displays the current chat session.
 */
public class BluetoothMusic extends Activity implements OnSeekBarChangeListener{
	
    // Debugging
    private static final String TAG = "BluetoothMusic";
    private static final boolean D = true;

    // Message types sent from the BluetoothChatService Handler
    public static final int MESSAGE_STATE_CHANGE = 1;
    public static final int MESSAGE_READ = 2;
    public static final int MESSAGE_WRITE = 3;
    public static final int MESSAGE_DEVICE_NAME = 4;
    public static final int MESSAGE_TOAST = 5;

    // Key names received from the BluetoothChatService Handler
    public static final String DEVICE_NAME = "device_name";
    public static final String TOAST = "toast";

    // Intent request codes
    private static final int REQUEST_CONNECT_DEVICE = 1;
    private static final int REQUEST_ENABLE_BT = 2;

    // Layout Views
    private TextView mTitle;
    Button bt_shareAndReceive;
    
    //Stop music
    Button bt_stop;
    
    //TextView for send or receive
    TextView txt_nameDevice;
    TextView txt_nameSong;

    // Name of the connected device
    private String mConnectedDeviceName = null;
    // Local Bluetooth adapter
    private BluetoothAdapter mBluetoothAdapter = null;
    // Member object for the chat services
    private BluetoothService mChatService = null;
    
    
    MediaPlayer media;
    static final UUID MY_UUID = UUID
			.fromString("fa87c0d0-afac-11de-8a39-0800200c9a99");
    String AddressDevice;
    String AddressFile;
    InputStream in;
    
    //Path song
    String nameSong = "";
    String tempNameSong = "";
    String pathSong = "";
    
    //Stop thread
    //String stop = "";
    
    //Share or Receive
    boolean shareOrReceive = false;
    
    //Thread Accept and Send
    AcceptData accept;
    SendData send;
    
    //Set title
    TextView txt_left;
    
    //Handler xu ly progressbar
    Handler handler = new Handler();
    Handler handlerSocket = new Handler();
    
    Utilities utils;
    SeekBar songProgressBar;
    File ssss;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        if(D) Log.e(TAG, "+++ ON CREATE +++");

         //ssss = new File(this.getExternalCacheDir(), "vcsMusic.mp3");
        
        // Set up the window layout
        requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
        setContentView(R.layout.main);
        getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);

        // Set up the custom title
        mTitle = (TextView) findViewById(R.id.title_left_text);
        mTitle.setText(R.string.app_name);
        mTitle = (TextView) findViewById(R.id.title_right_text);

        // Get local Bluetooth adapter
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        // If the adapter is null, then Bluetooth is not supported
        if (mBluetoothAdapter == null) {
            Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
            finish();
            return;
        }
        
        
        utils = new Utilities();
        songProgressBar = (SeekBar)findViewById(R.id.seekBar);
        songProgressBar.setOnSeekBarChangeListener(BluetoothMusic.this);
        
        txt_left = (TextView)findViewById(R.id.title_left_text);
        txt_nameDevice = (TextView)findViewById(R.id.nameDevice);
        txt_nameSong = (TextView)findViewById(R.id.nameSong);
        bt_shareAndReceive = (Button)findViewById(R.id.bt_shareAndReceive);
        bt_stop = (Button)findViewById(R.id.bt_stopStream);
        
        Intent getIntent = this.getIntent();
        Bundle bundle = getIntent.getExtras();
        pathSong = bundle.getString("PathSong");
        nameSong = bundle.getString("NameSong");
        shareOrReceive = bundle.getBoolean("Share");
        Toast.makeText(BluetoothMusic.this, bundle.getString("NameSong"), Toast.LENGTH_LONG).show();
        
        if(shareOrReceive == false){
        	txt_left.setText("Receive Music");
        	//bt_shareAndReceive.setText("Receive Music");
        	bt_shareAndReceive.setVisibility(View.INVISIBLE);
        }else{
        	txt_left.setText("Share Music");
        	//bt_shareAndReceive.setText("Send Music");
        	txt_nameSong.setText(nameSong);
        }
        
        
        bt_shareAndReceive.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				if(shareOrReceive == false){
		        	accept = new AcceptData();
		        	accept.start();
		        	init();
		        }else{
		        	//sendMessage("sendingforme");
		        	send = new SendData();
		        	send.sendFile();
		        	sendMessage("vcsvcs"+nameSong);
		        	bt_shareAndReceive.setEnabled(false);
		        }
				
			}
		});
        
        bt_stop.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				sendMessage("stop");
			}
		});
        
    }

    @Override
    public void onStart() {
        super.onStart();
        if(D) Log.e(TAG, "++ ON START ++");

        // If BT is not on, request that it be enabled.
        // setupChat() will then be called during onActivityResult
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
        // Otherwise, setup the chat session
        } else {
            if (mChatService == null) setupChat();
        }
    }

    @Override
    public synchronized void onResume() {
        super.onResume();
        if(D) Log.e(TAG, "+ ON RESUME +");

        // Performing this check in onResume() covers the case in which BT was
        // not enabled during onStart(), so we were paused to enable it...
        // onResume() will be called when ACTION_REQUEST_ENABLE activity returns.
        if (mChatService != null) {
            // Only if the state is STATE_NONE, do we know that we haven't started already
            if (mChatService.getState() == BluetoothService.STATE_NONE) {
              // Start the Bluetooth chat services
              mChatService.start();
            }
        }
    }

    private void setupChat() {
        Log.d(TAG, "setupChat()");
        mChatService = new BluetoothService(this, mHandler);
    }

    @Override
    public synchronized void onPause() {
        super.onPause();
        if(D) Log.e(TAG, "- ON PAUSE -");
    }

    @Override
    public void onStop() {
        super.onStop();
        if(D) Log.e(TAG, "-- ON STOP --");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // Stop the Bluetooth chat services
        if (mChatService != null) mChatService.stop();
        if(D) Log.e(TAG, "--- ON DESTROY ---");
      
        if(media != null){
        	media.stop();
            media.release();
        }
        
        if(accept != null){
        	accept.Cancel();
        }
        
        if(in != null){
        	try {
    			in.close();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
        }
        
        handler.removeCallbacks(mUpdateTimeTask);
        handlerSocket.removeCallbacks(listenRun);
    }

    private void ensureDiscoverable() {
        if(D) Log.d(TAG, "ensure discoverable");
        if (mBluetoothAdapter.getScanMode() !=
            BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
            Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
            discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
            startActivity(discoverableIntent);
        }
    }

    /**
     * Sends a message.
     * @param message  A string of text to send.
     */
    private void sendMessage(String message) {
    	if (mChatService.getState() != BluetoothService.STATE_CONNECTED) {
            Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
            return;
        }

        // Check that there's actually something to send
        if (message.length() > 0) {
            // Get the message bytes and tell the BluetoothChatService to write
            byte[] send = message.getBytes();
            mChatService.write(send);
        }
    }

    // The action listener for the EditText widget, to listen for the return key
    private TextView.OnEditorActionListener mWriteListener =
        new TextView.OnEditorActionListener() {
        public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
            // If the action is a key-up event on the return key, send the message
            if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {
                String message = view.getText().toString();
                //sendMessage(message);
            }
            if(D) Log.i(TAG, "END onEditorAction");
            return true;
        }
    };

    
    public void updateProgressBar(){
		handler.postDelayed(mUpdateTimeTask, 100);
		//txt_nameDevice.setText(mConnectedDeviceName);
		
	}
    
    public void listenSocket(){
    	handlerSocket.postDelayed(listenRun, 100);
    }
    
    Runnable listenRun = new Runnable() {
		
		@Override
		public void run() {
			// TODO Auto-generated method stub
			if(mConnectedDeviceName != null)
		    	if(shareOrReceive == false){
		    		Toast.makeText(getApplicationContext(), "Da ket noi roi", Toast.LENGTH_SHORT).show();
		    		accept = new AcceptData();
		        	accept.start();
		        	init();
		        }
		}
	};
	
	Runnable mUpdateTimeTask = new Runnable() {
		
		@Override
		public void run() {
			long totalDuration = media.getDuration();
			long currentDuration = media.getCurrentPosition();
			
//			tv_realTime.setText("" + utils.milliSecondsToTimer(currentDuration));
//			tv_sizeFile.setText("" + utils.milliSecondsToTimer(totalDuration));
			
			int progress = (int)(utils.getProgressPercentage(currentDuration, totalDuration));
			songProgressBar.setProgress(progress);
			handler.postDelayed(this, 100);
		}
	};
    
    // The Handler that gets information back from the BluetoothChatService
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MESSAGE_STATE_CHANGE:
                if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
                switch (msg.arg1) {
                case BluetoothService.STATE_CONNECTED:
                    mTitle.setText(R.string.title_connected_to);
                    mTitle.append(mConnectedDeviceName);
                    txt_nameDevice.setText("...");
                    txt_nameDevice.setText(mConnectedDeviceName);
                   
                    break;
                case BluetoothService.STATE_CONNECTING:
                    mTitle.setText(R.string.title_connecting);
                    break;
                case BluetoothService.STATE_LISTEN:
                case BluetoothService.STATE_NONE:
                    mTitle.setText(R.string.title_not_connected);
                    break;
                }
                break;
            case MESSAGE_WRITE:
                byte[] writeBuf = (byte[]) msg.obj;
                // construct a string from the buffer
                String writeMessage = new String(writeBuf);
//                mConversationArrayAdapter.add("Me:  " + writeMessage);
                
                
                
                if(writeMessage.equals("success")){
                	media = new MediaPlayer();
            		try {
            			media.setDataSource(AddressFile);
            			media.setAudioStreamType(AudioManager.STREAM_MUSIC);
            			//Log.e("s", bufferedFile.getAbsolutePath());
            			media.prepare();
            			media.start();
            			songProgressBar.setProgress(0);
            			songProgressBar.setMax(100);
            			updateProgressBar();
            	 		
            		} catch (IllegalArgumentException e) {
            			e.printStackTrace();
            		} catch (IllegalStateException e) {
            			e.printStackTrace();
            		} catch (IOException e) {
            			e.printStackTrace();
            		}
                }
                
                if(writeMessage.equals("stop")){
                	
                	media.pause();
                	finish();
                }
                
                
                break;
            case MESSAGE_READ:
                byte[] readBuf = (byte[]) msg.obj;
                // construct a string from the valid bytes in the buffer
                String readMessage = new String(readBuf, 0, msg.arg1);
//                mConversationArrayAdapter.add(mConnectedDeviceName+":  " + readMessage);
//        		if(readMessage.equals("stop")){
//        			media.pause();
//                }
                
                
                
                if(readMessage.substring(0, 6).equals("vcsvcs")){
                	txt_nameSong.setText(readMessage.substring(6, readMessage.length()));
                }
                
                if(readMessage.equals("success"))
        		{
        			media = new MediaPlayer();
            		try {
            			//media.setDataSource(getAssets().openFd("sample.mp3").getFileDescriptor());
            			//File fullPath = new File(pathSong);
            			media.setDataSource(pathSong);
            			media.setAudioStreamType(AudioManager.STREAM_MUSIC);
            			media.prepare();
            			media.start();
            			songProgressBar.setProgress(0);
            			songProgressBar.setMax(100);
            			updateProgressBar();
            	 		
            		} catch (IllegalArgumentException e) {
            			e.printStackTrace();
            		} catch (IllegalStateException e) {
            			e.printStackTrace();
            		} catch (IOException e) {
            			e.printStackTrace();
            		}
        		}
                
                if(readMessage.equals("stop")){
                	media.pause();
                	finish();
                }
        		
                break;
            case MESSAGE_DEVICE_NAME:
                // save the connected device's name
                mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
                //txt_nameDevice.setText(msg.getData().getString(DEVICE_NAME));
                Toast.makeText(getApplicationContext(), "Connected to "
                               + mConnectedDeviceName, Toast.LENGTH_SHORT).show();
                listenSocket();
                break;
            case MESSAGE_TOAST:
                Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),
                               Toast.LENGTH_SHORT).show();
                break;
            }
            
            
        }
    };
    
    public void init(){
	     InputStream fIn = null;
	     fIn = in;
	     
	     String filename = "vcsMusic.mp3";
	     File fullPath = new File(this.getExternalCacheDir(), filename);
	     try {
			fullPath.createNewFile();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	     Log.e("s",this.getCacheDir().toString());
	     OutputStream save = null;
	     try {
	         try {
				save = new FileOutputStream(fullPath);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
	         byte[] bu = new byte[1024];
	         int c;
	         try {
				while ((c = fIn.read(bu)) != -1) {
				    try {
						save.write(bu, 0, c);
					} catch (IOException e) {
						e.printStackTrace();
					}
				 }
			} catch (IOException e) {
				e.printStackTrace();
			}
	      }finally {
	         if (fIn != null) {
	            try {
					save.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
	         }
	         if (save != null) {
	            try {
					save.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
	         }
	      }
	     
	     
	     AddressFile = fullPath.toString();
	     sendMessage("success");
	     
    }
    
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(D) Log.d(TAG, "onActivityResult " + resultCode);
        switch (requestCode) {
        case REQUEST_CONNECT_DEVICE:
            // When DeviceListActivity returns with a device to connect
            if (resultCode == Activity.RESULT_OK) {
                // Get the device MAC address
                String address = data.getExtras()
                                     .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
                AddressDevice = address;
                
                //Toast.makeText(getApplicationContext(), AddressDevice, Toast.LENGTH_SHORT).show();
                // Get the BLuetoothDevice object
                BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
                
                // Attempt to connect to the device
                mChatService.connect(device);
                
            }
            break;
        case REQUEST_ENABLE_BT:
            // When the request to enable Bluetooth returns
            if (resultCode == Activity.RESULT_OK) {
                // Bluetooth is now enabled, so set up a chat session
                setupChat();
            } else {
                // User did not enable Bluetooth or an error occured
                Log.d(TAG, "BT not enabled");
                Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
                finish();
            }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.option_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    	if(shareOrReceive == true){
    		switch (item.getItemId()) {
            case R.id.scan:
                // Launch the DeviceListActivity to see devices and do scan
                Intent serverIntent = new Intent(this, DeviceListActivity.class);
                startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
                return true;
            case R.id.discoverable:
                // Ensure this device is discoverable by others
                ensureDiscoverable();
                return true;
            }
    	}
        return false;
    }
    
    
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
        	if(media != null){
        		media.pause();
        	}
        	
        	if(accept != null){
        		accept.Cancel();
        	}
            finish();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
    
    
    
    
    class SendData extends Thread {
		private BluetoothDevice device = null;
		private BluetoothSocket btSocket = null;
		private OutputStream outStream = null;

		public SendData() {

			device = mBluetoothAdapter.getRemoteDevice(AddressDevice);
			try {
				btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
			} catch (Exception e) {

			}
			mBluetoothAdapter.cancelDiscovery();
			try {
				btSocket.connect();
			} catch (IOException e) {
				try {
					btSocket.close();
				} catch (IOException e2) {
				}
			}
			Toast.makeText(getBaseContext(),
					"Connected to " + device.getName(), Toast.LENGTH_SHORT)
					.show();
			try {
				outStream = btSocket.getOutputStream();
			} catch (IOException e) {
			}
		}
		
		public void sendFile() {
			try {
				//mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
				//InputStream inStream = getAssets().open("sample.mp3");
				InputStream inStream = new BufferedInputStream(new FileInputStream(pathSong));

		        
		        byte[] buffer = new byte[1024];
		        int c;
		        try {
					while ((c = inStream.read(buffer)) != -1) {
					    try {
					    	outStream.write(buffer, 0, c);
						} catch (IOException e) {
							Log.e("Loi", "Loi ghi file");
						}
					 }
				} catch (IOException e) {
					e.printStackTrace();
				}finally {
			         if (outStream != null) {
				            try {
				            	outStream.close();
				            	outStream.flush();
							} catch (IOException e) {
								e.printStackTrace();
							}
				         }
				         if (outStream != null) {
				            try {
				            	outStream.close();
				            	outStream.flush();
							} catch (IOException e) {
								e.printStackTrace();
								Log.e("Loi", "loi loi loi loi.");
							}
				         }
				      }
		        outStream.flush();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
				Log.e("Loi", "loi o cho nay sao ta.");
			}
		}
		
		public void Cancel(){
			try {
				btSocket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

    
    
    
    class AcceptData extends Thread {
		private final BluetoothServerSocket mmServerSocket;
		private BluetoothSocket socket = null;
		private String device;

		public AcceptData() {
			BluetoothServerSocket tmp = null;
			try {
				tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(
						"Bluetooth", MY_UUID);
			} catch (IOException e) {
				
			}
			mmServerSocket = tmp;
			try {
				socket = mmServerSocket.accept();
			} catch (IOException e) {
				
			}
			device = socket.getRemoteDevice().getName();
			Toast.makeText(getBaseContext(), "Connected to " + device,
					Toast.LENGTH_SHORT).show();
			try {
				in = socket.getInputStream();
			} catch (IOException e) {
			
			}
		}//AcceptThread
		
		public void Cancel(){
			
			if(in != null){
				try {
					in.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
			
			if(mmServerSocket != null){
				try {
					mmServerSocket.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			if(socket != null){
				try {
					socket.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		}
    }




	@Override
	public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onStartTrackingTouch(SeekBar seekBar) {
		// TODO Auto-generated method stub
		handler.removeCallbacks(mUpdateTimeTask);
	}

	@Override
	public void onStopTrackingTouch(SeekBar seekBar) {
		// TODO Auto-generated method stub
		handler.removeCallbacks(mUpdateTimeTask);
		int totalDuration = (int)media.getDuration();
        int currentPosition = utils.progressToTimer(seekBar.getProgress(), totalDuration);
 
        // forward or backward to certain seconds
        media.seekTo(currentPosition);
 
        // update timer progress again
        updateProgressBar();
	}
}